/*
 * dsmRequestor.cpp
 *
 *  Created on: Dec 15, 2013
 *      Author: m
 */

#include <cstring>
#include "DSMComun.h"
#include "SharedMemory2.h"
#include "MessageQueue.h"
#include "ColaRemotaTransmisor.h"
#include "ColaRemotaReceptor.h"
#include "CPrinter.h"
#include "StringUtils.h"
#include "Robot11AProductor.h"
#include "Cinta15.h"
#include "Cinta13B.h"
#include "Cinta13A.h"
#include "Robot11BProductor.h"
#include "Robot14Consumidor.h"
#include "Robot14Productor.h"
#include "Robot16Consumidor.h"
#include "../../middleware/CommunicationRobot11.h"
#include "../../middleware/CommunicationRobot12.h"
#include "../../middleware/CommunicationRobot5.h"
#include "../../middleware/MiddlewareCommon.h"
#include "../../middleware/CommunicationPrimerCinta.h"

using ipc::MessageQueue;
using ipc::CPrinter;
using ipc::SharedMemory2;
using namespace middleware;

int main ( int argc, char* argv[] )
{
	std::string requestorName;
	std::string colaRespuesta;

	if (!DSM_ENABLED)
	{
        CPrinter::printErr( "ERROR: EL SERVICIO DSM ESTA APAGADO!" );
		exit ( 0 );
	}

	CPrinter::setHeader( "dsmRequestor" );

	if ( argc != 2 )
	{
		CPrinter::printErr( "Cantidad de argumentos invalidos" );
		exit( 1 );
	}

	requestorName = argv[1];

	CPrinter::setHeader( "dsmRequestor " + requestorName );

    CPrinter::printOut( "INICIADO" );

	colaRespuesta = requestorName + ".dsmresp";

	MessageQueue<PedidoDSM> colaPedidos =
			MessageQueue<PedidoDSM>::get( "/tmp/" + requestorName + "shm.ipc", COLA_PEDIDO_HOST );
	MessageQueue<TokenDSM> colaEntrega =
			MessageQueue<TokenDSM>::get( "/tmp/" + requestorName + "shm.ipc", COLA_ENTREGA_HOST );

	// Creo los transmisores y receptores de mensajes de DSM
	ColaRemotaTransmisor transmisor;
	ColaRemotaReceptor receptor( colaRespuesta );

	while ( true )
	{
		std::string colaDestino;
		PedidoDSM  pedido;
		TokenDSM entrega;

		pedido = colaPedidos.get( 0 );

		CPrinter::printOut( "Enviando pedido con shmid: %d", pedido.idDSM );

		strcpy( pedido.colaRespuesta, colaRespuesta.c_str() );

		colaDestino = COLA_PEDIDO_BROKER_BASENAME + StringUtils::NumberToString( pedido.idDSM );

		transmisor.enviarMensaje<PedidoDSM>( colaDestino, pedido );

		CPrinter::printOut( "Esperando Token: %d", pedido.idDSM );
		entrega = receptor.recibirMensaje<TokenDSM>();
		CPrinter::printOut( "Recibi el Token: %d", entrega.idDSM );

		CPrinter::printOut( "Actualizando la shmem: %d", entrega.idDSM );

		switch ( entrega.idDSM )
		{
		case DSMID_TEST:
		{
			ContadorDistribuido *p = SharedMemory2<ContadorDistribuido>::get( DSM_IPC_BASEFILE, SHM_TEST );
			memcpy( p, entrega.data, sizeof(ContadorDistribuido) );
		}
		break;

		case DSMID_CINTA13A:
		{
			Cinta3Slots *p = SharedMemory2<Cinta3Slots>::get( Cinta13A::s_ipcBaseFile, Cinta13A::s_cintaKey );
			memcpy( p, entrega.data, sizeof(Cinta3Slots) );
		}
		break;

		case DSMID_CINTA13B:
		{
			Cinta3Slots *p = SharedMemory2<Cinta3Slots>::get( Cinta13B::s_ipcBaseFile, Cinta13B::s_cintaKey );
			memcpy( p, entrega.data, sizeof(Cinta3Slots) );
		}
		break;

		case DSMID_CINTA15:
		{
			Cinta5Slots *p = SharedMemory2<Cinta5Slots>::get( Cinta15::s_ipcBaseFile, Cinta15::s_cintaKey );
			memcpy( p, entrega.data, sizeof(Cinta5Slots) );
		}
		break;

		case DSMID_R11APROD:
		{
			bool *p = SharedMemory2<bool>::get( Robot11AProductor::s_ipcBaseFile, Robot11AProductor::s_esperaEspacioKey );
			memcpy( p, entrega.data, sizeof(bool) );
		}
		break;

		case DSMID_R11BPROD:
		{
			bool *p = SharedMemory2<bool>::get( Robot11BProductor::s_ipcBaseFile, Robot11BProductor::s_esperaEspacioKey );
			memcpy( p, entrega.data, sizeof(bool) );
		}
		break;

		case DSMID_R14CONS:
		{
			bool *p = SharedMemory2<bool>::get( Robot14Consumidor::s_ipcBaseFile, Robot14Consumidor::s_esperaProductoKey );
			memcpy( p, entrega.data, sizeof(bool) );
		}
		break;

		case DSMID_R14PROD:
		{
			bool *p = SharedMemory2<bool>::get( Robot14Productor::s_ipcBaseFile, Robot14Productor::s_esperaEspacioKey );
			memcpy( p, entrega.data, sizeof(bool) );
		}
		break;

		case DSMID_R16CONS:
		{
			bool *p = SharedMemory2<bool>::get( Robot16Consumidor::s_ipcBaseFile, Robot16Consumidor::s_esperaProductoKey );
			memcpy( p, entrega.data, sizeof(bool) );
		}
		break;

		case DSMID_PRIMERCINTA_IZQ:
		{
			CintaProductos *p = SharedMemory2<CintaProductos>::get( middleware::CommunicationPrimerCinta::CINTA_SHMEM_PATH, middleware::CommunicationPrimerCinta::CINTA_SHMEM_KEY_IZQ );
			memcpy( p, entrega.data, sizeof(CintaProductos) );
		}
		break;

		case DSMID_PRIMERCINTA_DER:
		{
			CintaProductos *p = SharedMemory2<CintaProductos>::get( middleware::CommunicationPrimerCinta::CINTA_SHMEM_PATH, middleware::CommunicationPrimerCinta::CINTA_SHMEM_KEY_DER );
			memcpy( p, entrega.data, sizeof(CintaProductos) );
		}
		break;

		case DSMID_CANASTOS_IZQ:
		{
			MemCanastos *p = SharedMemory2<MemCanastos>::get( middleware::CommunicationCanastos::AGV_SHMEM_CANASTOS_PATH, middleware::CommunicationCanastos::AGV_SHMEM_CANASTOS_KEY_IZQ );
			memcpy( p, entrega.data, sizeof(MemCanastos) );
		}
		break;

		case DSMID_CANASTOS_DER:
		{
			MemCanastos *p = SharedMemory2<MemCanastos>::get( middleware::CommunicationCanastos::AGV_SHMEM_CANASTOS_PATH, middleware::CommunicationCanastos::AGV_SHMEM_CANASTOS_KEY_DER );
			memcpy( p, entrega.data, sizeof(MemCanastos) );
		}
		break;

		case DSMID_CANASTOS_MED:
		{
			MemCanastos *p = SharedMemory2<MemCanastos>::get( middleware::CommunicationCanastos::AGV_SHMEM_CANASTOS_PATH, middleware::CommunicationCanastos::AGV_SHMEM_CANASTOS_KEY_MED );
			memcpy( p, entrega.data, sizeof(MemCanastos) );
		}
		break;

		case DSMID_EROBOT11_IZQ:
		{
			EstadoRobotPiezas *p = SharedMemory2<EstadoRobotPiezas>::get( CommunicationRobot11::ROBOT11_SHMEM_PATH, CommunicationRobot11::ROBOT11_SHMEM_KEY_IZQ );
			memcpy( p, entrega.data, sizeof(EstadoRobotPiezas) );
		}
		break;

		case DSMID_EROBOT11_DER:
		{
			EstadoRobotPiezas *p = SharedMemory2<EstadoRobotPiezas>::get( CommunicationRobot11::ROBOT11_SHMEM_PATH, CommunicationRobot11::ROBOT11_SHMEM_KEY_DER );
			memcpy( p, entrega.data, sizeof(EstadoRobotPiezas) );
		}
		break;

		case DSMID_EROBOT12_IZQ:
		{
			EstadoRobotPiezas *p = SharedMemory2<EstadoRobotPiezas>::get( CommunicationRobot12::ROBOT12_SHMEM_PATH,CommunicationRobotPiezas::getAltKey(CommunicationRobot12::ROBOT12_SHMEM_KEY_IZQ));
			memcpy( p, entrega.data, sizeof(EstadoRobotPiezas) );
		}
		break;

		case DSMID_EROBOT12_DER:
		{
			EstadoRobotPiezas *p = SharedMemory2<EstadoRobotPiezas>::get( CommunicationRobot12::ROBOT12_SHMEM_PATH, CommunicationRobotPiezas::getAltKey(CommunicationRobot12::ROBOT12_SHMEM_KEY_DER));
			memcpy( p, entrega.data, sizeof(EstadoRobotPiezas) );
		}
		break;

		case DSMID_LISTOROBOT12_IZQ:
		{
			Robot12Listo *p = SharedMemory2<Robot12Listo>::get( CommunicationRobot12::ROBOT12_SHMEM_PATH, CommunicationRobot12::ROBOT12_SHMEM_KEY_IZQ);
			memcpy( p, entrega.data, sizeof(Robot12Listo) );
		}
		break;

		case DSMID_LISTOROBOT12_DER:
		{
			Robot12Listo *p = SharedMemory2<Robot12Listo>::get( CommunicationRobot12::ROBOT12_SHMEM_PATH, CommunicationRobot12::ROBOT12_SHMEM_KEY_DER);
			memcpy( p, entrega.data, sizeof(Robot12Listo) );
		}
		break;

		case DSMID_EROBOT5:
		{
			EstadoRobot5 *p = SharedMemory2<EstadoRobot5>::get( CommunicationRobot5::R5_SHMEM_PATH, CommunicationRobot5::R5_SHMEM_ESTADO_KEY);
			memcpy( p, entrega.data, sizeof(EstadoRobot5) );
		}
		break;

		case DSMID_PENDROBOT5:
		{
			PendientesRobot5 *p = SharedMemory2<PendientesRobot5>::get( CommunicationRobot5::R5_SHMEM_PATH, CommunicationRobot5::R5_SHMEM_PENDIENTES_KEY);
			memcpy( p, entrega.data, sizeof(PendientesRobot5) );
		}
		break;

		default:
			throw Exception( "DSM: Unknown DSMID" );
			break;
		}

		CPrinter::printOut( "Entregando el token a: %s", requestorName.c_str() );
		colaEntrega.put( entrega.idDSM, entrega );
	}

	return 0;
}
